﻿using System;
using Framework.MVC;
using Log.Model;
using Billing.Model;
using Billing.Model.Behavior;
using Billing.IService.Entry;
using Framework.MVVM.Model;
using Common.IService;
using Common.Service;
using Log.Service;
using Log.IService;
using Billing.IService;
using Billing.Service;
using Common.IService.Entry;
using Config.IService;
using Config.Service;
using Config.Model;
using Framework.Extention.Filter;


namespace Billing.Models
{
    [ServiceAttribute(typeof(IConfigService), typeof(ConfigService), "Instance")]
    [ServiceAttribute(typeof(IBillingService), typeof(BillingService), "Instance")]
    [ServiceAttribute(typeof(ILogService), typeof(LogService), "Instance")]
    [ServiceAttribute(typeof(ICodeService), typeof(CodeService), "Instance")]
    public class ModifyBillingModel : AsyncModelBase, IWriteLog, IGetBilling, IModifyBilling, INewBilling, IGetConfig<IFilter<string>>
    {
        #region Field

        private const string m_ip_error = "billing00";
        private const string m_ip_complete = "billing01";
        private const string m_get_error = "billing02";
        private const string m_get_complete = "billing03";
        private const string m_modify_error = "billing04";
        private const string m_modify_complete = "billing05";
        private const string m_new_error = "billing06";
        private const string m_new_complete = "billing07";

        private const string m_result="result";

        #endregion Field

        #region Property

        public string Source { get; set; }

        public decimal Amount { get; set; }

        public bool Mode { get; set; }

        public string Address { get; set; }

        #endregion Property

        #region AsyncModelBase

        protected override void OnInit(Type type)
        {
            OnBeginRequest();
            this.GetConfig<IFilter<string>>(m_ip_error, m_ip_complete);
        }

        #endregion AsyncModelBase

        #region IWriteLog

        public void OnWriteLogComplete(string eventCode)
        {
            OnEndRequest();
        }

        public void OnWriteLogError(string eventCode)
        {
            OnEndRequest();
        }

        #endregion IWriteLog

        #region IGetConfig IP Filter

        public string ConfigName { get; set; }

        public void OnGetConfigComplete(string key, IFilter<string> entry)
        {
            bool validate = entry.Validate(Address);
            if (validate)
            {
                OnBeginRequest();
                this.GetBilling(m_get_error, m_get_complete);
            }
            this.Log(key, new SourceEntry<bool> { source = Source, data = validate });
        }

        public void OnGetConfigError(string key)
        {
            this.Log(key, Source);
        }

        #endregion IGetConfig IP Filter

        #region IGetBilling

        public string BillingCode { get; set; }

        public string BillingSource { get; set; }

        public void OnGetBillingComplete(string key, BillingEntry entry)
        {
            BillingAmount = Mode ? entry.amount + Amount : entry.amount - Amount;
            if (BillingAmount > 0)
            {
                OnBeginRequest();
                BillingVersion = entry.version;
                BillingTotalAmount = !Mode ? entry.totalAmount : entry.totalAmount + Amount;
                BillingTotalCost = Mode ? entry.totalCost : entry.totalCost + Amount;
                this.ModifyBilling(m_modify_error, m_modify_complete);
            }
            this.Log(key, new SourceEntry<BillingEntry> { source = Source, data = entry });
        }

        public void OnGetBillingError(string key)
        {
            if (Mode&&Amount > 0)
            {
                OnBeginRequest();
                BillingAmount = Amount;
                BillingTotalAmount = BillingAmount;
                BillingTotalCost = 0;
                this.NewBilling(m_new_complete,m_new_error);
            }
            this.Log(key, new SourceEntry<BillingEntry> { source = Source, data = new BillingEntry { code = BillingCode, sourceCode = BillingSource} });
        }

        #endregion IGetBilling

        #region IModifyBilling

        public decimal BillingAmount { get; set; }

        public decimal BillingTotalAmount { get; set; }

        public decimal BillingTotalCost { get; set; }

        public byte BillingVersion { get; set; }

        public void OnModifyBillingComplete(string key, BillingEntry entry)
        {
            OnComplete(m_result, true);
            this.Log(key, new SourceEntry<BillingEntry> { source = Source, data = entry });
        }

        public void OnModifyBillingError(string key)
        {
            this.Log(key, new SourceEntry<BillingEntry> { source = Source, data = new BillingEntry { code = BillingCode, sourceCode = BillingSource, amount = BillingAmount, totalAmount = BillingTotalAmount, totalCost = BillingTotalCost, version = BillingVersion } });
        }

        #endregion IModifyBilling

        #region INewBilling

        public void OnNewBillingComplete(string key, BillingEntry entry)
        {
            OnComplete(m_result, true);
            this.Log(key, new SourceEntry<BillingEntry> { source = Source, data = entry });
        }

        public void OnNewBillingError(string key)
        {
            this.Log(key, new SourceEntry<BillingEntry> { source = Source, data = new BillingEntry { code = BillingCode, sourceCode = BillingSource, amount = BillingAmount, totalAmount = BillingTotalAmount, totalCost = BillingTotalCost, version = BillingVersion } });
        }

        #endregion INewBilling
    }
}